package icu.zhhll.util;

import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import ma.glasnost.orika.metadata.ClassMapBuilder;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 对象拷贝(浅拷贝)
 *
 * @author zh
 * @date 2023/9/7 22:09
 */
public class SimpleCopy<T, V> {
    private static final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
    private final List<String> excludeFields = new ArrayList<>();
    private final Map<String, String> fieldMapping = new HashMap<>();
    private MapperFactory selfMapperFactory;

    /**
     * copy对象
     *
     * @param from 数据来源对象
     * @param to   数据目标对象
     */
    public void copy(T from, V to) {
        if (excludeFields.size() != 0 || fieldMapping.size() != 0) {
            selfMapperFactory = new DefaultMapperFactory.Builder().build();
            ClassMapBuilder classMapBuilder = selfMapperFactory.classMap(from.getClass(), to.getClass());
            registerExcludeField(classMapBuilder);
            registerFieldMapping(classMapBuilder);
            classMapBuilder.byDefault().register();
            selfMapperFactory.getMapperFacade().map(from, to);
        } else {
            mapperFactory.getMapperFacade().map(from, to);
        }
    }

    private void registerFieldMapping(ClassMapBuilder classMapBuilder) {
        if (fieldMapping.size() > 0) {
            for (Map.Entry<String, String> entry : fieldMapping.entrySet()) {
                classMapBuilder.field(entry.getKey(), entry.getValue());
            }
        }

    }

    /**
     * copy对象
     *
     * @param from    数据来源对象
     * @param toClass 数据目标类
     * @return
     */
    public V copy(T from, Class<V> toClass) {
        if (excludeFields.size() != 0 || fieldMapping.size() != 0) {
            selfMapperFactory = new DefaultMapperFactory.Builder().build();
            ClassMapBuilder classMapBuilder = selfMapperFactory.classMap(from.getClass(), toClass);
            registerExcludeField(classMapBuilder);
            registerFieldMapping(classMapBuilder);
            classMapBuilder.byDefault().register();
            return selfMapperFactory.getMapperFacade().map(from, toClass);
        } else {
            return mapperFactory.getMapperFacade().map(from, toClass);
        }
    }

    private void registerExcludeField(ClassMapBuilder classMapBuilder) {
        if (excludeFields.size() > 0) {
            for (String exclude : excludeFields) {
                classMapBuilder.exclude(exclude);
            }
        }

    }

    /**
     * copy集合
     *
     * @param from    数据来源对象集合
     * @param toClass 数据目标类
     * @return
     */
    public List<V> copyList(List<T> from, Class<V> toClass) {
        // fix bug
        if (excludeFields.size() != 0 || fieldMapping.size() != 0) {
            selfMapperFactory = new DefaultMapperFactory.Builder().build();
            if (from != null && !from.isEmpty()) {

                ClassMapBuilder classMapBuilder = selfMapperFactory.classMap(from.get(0).getClass(), toClass);
                registerExcludeField(classMapBuilder);
                registerFieldMapping(classMapBuilder);
                classMapBuilder.byDefault().register();
                return selfMapperFactory.getMapperFacade().mapAsList(from, toClass);
            }
            throw new RuntimeException("数据来源对象为空");
        } else {
            return mapperFactory.getMapperFacade().mapAsList(from, toClass);
        }
    }

    /**
     * 设置需要排除copy的字段
     *
     * @param excludeFieldName
     * @return
     */
    public SimpleCopy<T, V> excludeField(String excludeFieldName) {
        excludeFields.add(excludeFieldName);
        return this;
    }

    /**
     * copy的对象字段名称不同时，可以进行字段映射
     *
     * @param fromFieldName 数据来源字段名
     * @param toFieldName   数据目标字段名
     * @return
     */
    public SimpleCopy<T, V> fieldMapping(String fromFieldName, String toFieldName) {
        fieldMapping.put(fromFieldName, toFieldName);
        return this;
    }
}